﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MacomberMapSystem.Common.Serialization;
using MacomberMapSystem.Common.CIM;
using System.Drawing;
using MacomberMapSystem.Common.Exports;
using System.Xml;
using MacomberMapSystem.Common.Database;

namespace MacomberMapSystem.Common.User_Interfaces.One_Lines
{
    /// <summary>
    /// This class holds information on one-line values, such as MVA, MVAR ratings that will show in the labels
    /// </summary>
    public class MM_OneLine_Value
    {
        #region Variable declarations
        /// <summary>The source of our value, such as an AnalogValue</summary>
        public CIM_Element ValueSource;

        /// <summary>The element with which the value is associated</summary>
        public CIM_Element AssociatedElement;

        /// <summary>The XML element which the value is associated</summary>
        public XmlElement xElem;

        /// <summary>The orientation of this value</summary>
        public MM_OneLine_Element.enumOrientations Orientation
        {
            get
            {
                if (!FlipDirection)
                    return _Orientation;
                else if (_Orientation == MM_OneLine_Element.enumOrientations.Up)
                    return MM_OneLine_Element.enumOrientations.Down;
                else if (_Orientation == MM_OneLine_Element.enumOrientations.Down)
                    return MM_OneLine_Element.enumOrientations.Up;
                else if (_Orientation == MM_OneLine_Element.enumOrientations.Right)
                    return MM_OneLine_Element.enumOrientations.Left;
                else if (_Orientation == MM_OneLine_Element.enumOrientations.Left)
                    return MM_OneLine_Element.enumOrientations.Right;
                else
                    return _Orientation;
            }
            set
            {                
                _Orientation = value;
            }
        }

        private MM_OneLine_Element.enumOrientations _Orientation =  MM_OneLine_Element.enumOrientations.Unknown;

        /// <summary>Whether the orientation needs to be flipped due to series compensator near node issues</summary>
        public bool FlipDirection = false;

        /// <summary>
        /// Retrieve the name off our measurement
        /// </summary>
        public String Name
        {
            get
            {
                if (ValueSource == null)
                    return "";
                else if (ValueSource.TypeName == "etx:EPSMeter")
                    return ValueSource.Name + "\n" + ValueSource["etx:EPSMeter.RID"];
                else if (ValueSource.TypeName == "etx:ResourceNode")
                    return ValueSource.Name;
                else if (OutputMode == enumOutputMode.Netmom)
                    return ValueType.ToString();
                else
                {
                    CIM_Element Name = ValueSource.ParseSingle("AnalogValue>AnalogName", null);
                    if (Name == null)
                        Name = ValueSource.ParseSingle("DiscreteValue>DiscreteName", null);
                    if (Name != null)
                        return Name.Name;
                    else
                        return "?";
                }
            }
        }

        /// <summary>The collection of value types</summary>
        public enum enumValueType
        {
            /// <summary>A label that has a pointer bar (AC Line sement)</summary>
            LabelWithNavigation,
            /// <summary>A breaker or switch label</summary>
            BreakerSwitchLabel,
            /// <summary>A KV level</summary>
            KVLevel,
            /// <summary>An analog level</summary>
            AnalogLevel,
            /// <summary>An element's label</summary>
            Label,
            /// <summary>An AVR value</summary>
            AVRValue,
            /// <summary>A PSS value</summary>
            PSSValue,
            /// <summary>A transformer tap rating</summary>
            TapValue,
            /// <summary>The OTS frequency panel</summary>
            FrequencyPanel
        }

        /// <summary>Our output mode</summary>
        public enum enumOutputMode
        {
            /// <summary>Output for SCADA</summary>
            Scada,
            /// <summary>Output for Netmom</summary>
            Netmom,
        }

        /// <summary>Our output mode</summary>
        public enumOutputMode OutputMode
        {
            get { return _OutputMode; }
            set { _OutputMode = value; }
        }
        private enumOutputMode _OutputMode;


        /// <summary>The type of value being drawn</summary>
        public enumValueType ValueType
        {
            get { return _ValueType; }
            set { _ValueType = value; }
        }
        private enumValueType _ValueType;

        /// <summary>The positioning of the values</summary>
        public Rectangle Bounds
        {
            get { return _Bounds; }
            set { _Bounds = value; }
        }
        
        private Rectangle _Bounds;

        /// <summary>
        /// Report the left of the value
        /// </summary>
        public int Left
        {
            get { return _Bounds.Left; }
            set { _Bounds.X = value; }
        }

        /// <summary>
        /// Report the top of the value
        /// </summary>
        public int Top
        {
            get { return _Bounds.Top; }
            set { _Bounds.Y = value; }
        }

        /// <summary>
        /// Report the width of the value
        /// </summary>
        public int Width
        {
            get { return _Bounds.Width; }
            set { _Bounds.Width = value; }
        }

        /// <summary>
        /// Report the height of the value
        /// </summary>
        public int Height
        {
            get { return _Bounds.Height; }
            set { _Bounds.Height = value; }
        }


        /// <summary>
        /// Report the Right of the value
        /// </summary>
        public int Right
        {
            get { return _Bounds.Right; }
            set { _Bounds.Width = value - _Bounds.Left; }
        }

        /// <summary>
        /// Report the Bottom of the value
        /// </summary>
        public int Bottom
        {
            get { return _Bounds.Bottom; }
            set { _Bounds.Height = value - _Bounds.Top; }
        }

        /// <summary>
        /// Report the location of the value
        /// </summary>
        public Point Location
        {
            get { return _Bounds.Location; }
            set { _Bounds.Location = value; }
        }

        /// <summary>
        /// Report the size of the value
        /// </summary>
        public Size Size
        {
            get { return _Bounds.Size; }
            set { _Bounds.Size = value; }
        }

        /// <summary>
        /// Estimate the size of our element by the larger of the SCADA or NETMOM sizes
        /// </summary>
        public Size EstimatedSize
        {
            get
            {
                List<Size> SizesToCheck = new List<Size>();
                bool MeasureString = false;
                //If we're a label, measure our string
                if (ValueType == enumValueType.Label)
                    MeasureString = true;
                else if (ValueType == enumValueType.LabelWithNavigation)
                {
                    MeasureString = true;
                    SizesToCheck.Add(new Size(114, 17));
                }
                else if (ValueType == enumValueType.BreakerSwitchLabel && OutputMode == enumOutputMode.Netmom)
                    MeasureString = true;
                else if (ValueType == enumValueType.BreakerSwitchLabel && OutputMode == enumOutputMode.Scada)
                    MeasureString = true;
                    //SizesToCheck.Add(new Size(115, 35));

                else if (ValueType == enumValueType.KVLevel && OutputMode == enumOutputMode.Netmom)
                    SizesToCheck.Add(new Size(59, 18));
                else if (ValueType == enumValueType.KVLevel && OutputMode == enumOutputMode.Scada)
                    SizesToCheck.Add(new Size(101, 19));
                else if (ValueType == enumValueType.AnalogLevel && OutputMode == enumOutputMode.Netmom)                    
                    SizesToCheck.Add(new Size(92, AssociatedElement.TypeName == "cim:SynchronousMachine" ? 56 : 35));
                else if (ValueType == enumValueType.FrequencyPanel)
                    SizesToCheck.Add(new Size(92, 56));
                else if (ValueType == enumValueType.AnalogLevel && OutputMode == enumOutputMode.Scada)
                    SizesToCheck.Add(new Size(125, 17));
                else if (ValueType == enumValueType.AVRValue || ValueType == enumValueType.PSSValue)
                    return new Size(58, 15);
                else if (ValueType == enumValueType.TapValue)
                    return new Size(95, 15);
                else
                    throw new InvalidOperationException("Unknown value type: " + ValueType.ToString());

                if (MeasureString)
                    using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
                    using (Font f = new Font("Arial", 10))
                        if (AssociatedElement.TypeName == "cim:ACLineSegment" && ValueSource != null)
                        {
                            String SubName = String.IsNullOrEmpty(ValueSource["cim:IdentifiedObject.description"]) ? ValueSource.Name : ValueSource["cim:IdentifiedObject.description"];
                            SizesToCheck.Add(Size.Ceiling(g.MeasureString(SubName, f)));
                        }                      
                        else
                            SizesToCheck.Add(Size.Ceiling(g.MeasureString(MM_OneLine_Element.DescriptorText(AssociatedElement, null, false), f)));
                            

                //Now, pull in our maximum size
                int Width = 0, Height = 0;
                foreach (Size SizeToCheck in SizesToCheck)
                {
                    Width = Math.Max(Width, SizeToCheck.Width);
                    Height = Math.Max(Height, SizeToCheck.Height);
                }
                return new Size(Width, Height);
            }
        }
        
        #endregion

        #region Initialization

        /// <summary>
        /// Initialize a new value that comes in from an element (e.g., analog)
        /// </summary>
        /// <param name="ValueSource"></param>
        /// <param name="AssociatedElement"></param>
        /// <param name="ValueType"></param>
        /// <param name="OutputMode"></param>
        /// <param name="xElem"></param>
        /// <param name="FlipDirection"></param>
        /// <param name="Orientation"></param>
        public MM_OneLine_Value(CIM_Element ValueSource, CIM_Element AssociatedElement, enumValueType ValueType, enumOutputMode OutputMode, XmlElement xElem, bool FlipDirection, MM_OneLine_Element.enumOrientations Orientation)
        {
             this.ValueSource = ValueSource;
            this.AssociatedElement = AssociatedElement;
            this.ValueType = ValueType;
            this.OutputMode = OutputMode;
            this.xElem = xElem;
            this.FlipDirection = FlipDirection;
            this._Orientation = Orientation;
        }



        /// <summary>
        /// Initialize a new value that comes in from an element (e.g., analog)
        /// </summary>
        /// <param name="ValueSource"></param>
        /// <param name="AssociatedElement"></param>
        /// <param name="ValueType"></param>
        /// <param name="OutputMode"></param>
        /// <param name="xElem"></param>
        /// <param name="FlipDirection"></param>
        public MM_OneLine_Value(CIM_Element ValueSource, CIM_Element AssociatedElement, enumValueType ValueType, enumOutputMode OutputMode, XmlElement xElem, bool FlipDirection)
        {
            this.ValueSource = ValueSource;
            this.AssociatedElement = AssociatedElement;
            this.ValueType = ValueType;
            this.OutputMode = OutputMode;
            this.xElem = xElem;
            this.FlipDirection = FlipDirection;
        }



        /// <summary>
        /// Initialize a new value that is associated with an element
        /// </summary>        
        /// <param name="AssociatedElement"></param>
        /// <param name="ValueType"></param>
        /// <param name="OutputMode"></param>        
        /// <param name="xElem"></param>
        public MM_OneLine_Value(CIM_Element AssociatedElement, enumValueType ValueType, enumOutputMode OutputMode, XmlElement xElem)
        {
            this.ValueSource = null;
            this.AssociatedElement = AssociatedElement;
            this.ValueType = ValueType;
            this.OutputMode = OutputMode;
            this.xElem = xElem;
        }

        #endregion

        #region Identity
        /// <summary>
        /// Report an easy-to-read string
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            if (ValueSource == null)
                return String.Format("{0} {1} for {2} ({3},{4})-({5},{6}) - {7}", OutputMode,ValueType, AssociatedElement.ToString(), Left, Top, Right, Bottom, Orientation);
            else
                return String.Format("{0} {1} {2} for {3} ({4},{5})-({6},{7}) - {8}", OutputMode, Name, ValueType, AssociatedElement.ToString(), Left, Top, Right, Bottom, Orientation);
        }
        #endregion

        #region WebFG exporting
        /// <summary>
        /// Write our DDL identifier for this element
        /// </summary>
        /// <param name="OutStream"></param>
        /// <param name="SCADA"></param>
        /// <param name="BaseElement"></param>
        /// <param name="Orientation"></param>
        /// <param name="Offset"></param>
        /// <param name="OTS"></param>
        ///<param name="Synchroscopes"></param>
        ///<param name="Synchrocheck_Relays"></param>
        public void WriteDDL(MM_DDL_Exporter_Stream OutStream, bool SCADA, bool OTS, String Orientation, CIM_Element BaseElement, Point Offset, Dictionary<CIM_RdfID, bool> Synchroscopes, Dictionary<CIM_RdfID, bool> Synchrocheck_Relays)
        {
            MM_DDL_Exporter_Target Target = SCADA ? OutStream.SCADA : OTS ? OutStream.OTS : OutStream.NETMOM;

            //Determine the name, substation, and element type of our component
            String ElemName;

            if (AssociatedElement.TypeName == "cim:ACLineSegment" || AssociatedElement.TypeName == "cim:SeriesCompensator")
            {
                CIM_Element ParentLine = AssociatedElement.ParseSingle("cim:Line", null);
                ElemName = ParentLine.Name.ToUpper() + (ParentLine.InLinks.Length == 1 ? "" : AssociatedElement.Name.ToUpper());
            }
            else if (AssociatedElement.TypeName == "cim:SynchronousMachine")
                ElemName = AssociatedElement.ParseSingle("Unit", null).Name;
            else
                ElemName = AssociatedElement.Name.ToUpper();

            //Try and locate our substation
            CIM_Element Substation = AssociatedElement.Substation;
            if (Substation == null && ValueSource != null)
                Substation = ValueSource.Substation;

            //Determine our element type
            String ElemType;
            if (AssociatedElement.TypeName == "cim:ACLineSegment")
                ElemType = (!SCADA && (String.IsNullOrEmpty(AssociatedElement["cim:Conductor.x"]) || AssociatedElement["cim:Conductor.x"] == "0") && (String.IsNullOrEmpty(AssociatedElement["cim:Conductor.r"]) || AssociatedElement["cim:Conductor.r"] == "0")) ? "ZBR" : "LN";
            else if (AssociatedElement.TypeName == "cim:SeriesCompensator")
                ElemType = (!SCADA && (String.IsNullOrEmpty(AssociatedElement["cim:SeriesCompensator.x"]) || AssociatedElement["cim:SeriesCompensator.x"] == "0") && (String.IsNullOrEmpty(AssociatedElement["cim:SeriesCompensator.r"]) || AssociatedElement["cim:SeriesCompensator.r"] == "0")) ? "ZBR" : "LN";                
                //ElemType = "LN";
            else if (AssociatedElement.TypeName == "cim:SynchronousMachine")
                ElemType = "UN";
            else if (AssociatedElement.TypeName == "cim:PowerTransformer" || AssociatedElement.TypeName == "cim:TransformerWinding")
                ElemType = "XF";
            else if (AssociatedElement.TypeName == "cim:ShuntCompensator")
                ElemType = "CP";
            else if (AssociatedElement.TypeName == "cim:StaticVarCompensator")
                ElemType = "SVS";
            else if (AssociatedElement.TypeName.EndsWith("Load"))
                ElemType = "LD";
            else if (AssociatedElement.TypeName == "cim:Breaker")
                ElemType = "CB";
            else if (AssociatedElement.TypeName == "cim:Disconnector" || AssociatedElement.TypeName == "cim:GroundDisconnector")
                ElemType = "DSC";
            else if (AssociatedElement.TypeName == "cim:ConnectivityNode")
                ElemType = "BS";
            else if (AssociatedElement.TypeName == "etx:PricingVector")
                ElemType = "PV";
            else if (AssociatedElement.TypeName == "cim:Contingency")
                ElemType = "CTG";
            else if (AssociatedElement.TypeName == "cim:Substation")
                ElemType = "ST";
            else if (AssociatedElement.TypeName == "etx:EndCap")
                ElemType = "EC";
            else
                ElemType = "??";



            Point Location = new Point(this.Location.X + Offset.X, this.Location.Y + Offset.Y);
            if (this.ValueType == enumValueType.Label)
                if (this.AssociatedElement.TypeName == "etx:PricingVector")
                    Target.WriteTextWithCam(this.Name, "PV_SHOW_NETMOM", Location, "LightGray", "Black", "Arial", 10, false, false, false, false, false);
                else if (ElemType == "XF" && !SCADA)
                {
                    //Find the primary winding
                    CIM_Element PrimaryWinding = null;
                    foreach (CIM_Element Winding in AssociatedElement.Parse("cim:TransformerWinding", null))
                        if (Winding.TypeName == "cim:TransformerWinding" && Winding.Attributes["cim:TransformerWinding.windingType"].Contains("primary"))
                            PrimaryWinding = Winding;
                    Target.WriteDataBoundPicture("DTS_" + ElemType + "_LABEL_NET", Location, "ST=" + AssociatedElement.Substation.Name, ElemType + "=" + PrimaryWinding.Name);
                    //if (BaseElement is CIM_Trace == false)//[ago] CR55198; to be part of future release
                    //    Target.WriteDataBoundPicture("OUTAGE_TYPE", Location, "MASEQP=" + AssociatedElement.TEID); //[ago] CR55198
                }
                else if (!SCADA && Array.IndexOf("CP,XF,SVS,UN,LD".Split(','), ElemType) != -1)
                {
                    Target.WriteDataBoundPicture("DTS_" + ElemType + "_LABEL_NET", Location, "ST=" + AssociatedElement.Substation.Name, ElemType + "=" + ElemName);
                    if (BaseElement is CIM_Trace == false)//[ago] CR55198
                        if(ElemType != "XF")
                            Target.WriteDataBoundPicture("OUTAGE_TYPE", Location, "MASEQP=" + AssociatedElement.TEID); //[ago] CR55198
                }
                else
                {
                    Target.WriteTextWithGab(MM_OneLine_Element.DescriptorText(AssociatedElement, null, false), "TEXT_FV_CHR_NONENTRY_SIMPLE_ERCOT", Location, false, false);
                    if (BaseElement is CIM_Trace == false)//[ago] CR55198
                        if (ElemType != "BS" && ElemType != "EC" && ElemType != "XF") //Loads will be part of the initial CR55198 release
                            Target.WriteDataBoundPicture("OUTAGE_TYPE", Location, "MASEQP=" + AssociatedElement.TEID); //[ago] CR55198
                }

            else if (this.ValueType == enumValueType.KVLevel)
                if (SCADA)
                {
                    CIM_Element Meas = ValueSource.ParseSingle("AnalogValue>Calculation", null);
                    if (Meas == null)
                        Meas = ValueSource.ParseSingle("AnalogValue>MeasurementGroup", null);
                    Target.WriteDataBoundPicture("KV_BUS", Location, "SUBSTN=" + Substation.Name, "DEVTYP=" + ElemType, "DEVICE=" + ElemName, "MEAS=" + Meas.Name, "ANALOG=" + ValueSource.ParseSingle("AnalogValue>AnalogName", null).Name);
                }
                else
                    Target.WriteDataBoundPicture("KV_NETWORK", Location, "ST=" + Substation.Name.ToUpper(), "ND=" + ElemName);
            else if (this.ValueType == enumValueType.LabelWithNavigation)
            {
                List<String> SubNames = new List<string>();
                if (AssociatedElement is CIM_Trace)                
                    SubNames.Add((AssociatedElement as CIM_Trace).Name);                    
                else
                {
                    SubNames.Add(String.IsNullOrEmpty(ValueSource["cim:IdentifiedObject.description"]) ? ValueSource.Name : ValueSource["cim:IdentifiedObject.description"]);
                    SubNames.Add(ValueSource.Name);
                    CIM_Element ParentLine = AssociatedElement.ParseSingle("cim:Line", null);
                    SubNames.Add(ParentLine.Name + (ParentLine.InLinks.Length == 1 ? "" : AssociatedElement.Name));                    
                }
                Point LblLocation = new Point(Location.X - (EstimatedSize.Width - Width) / 2, Location.Y);
                if (AssociatedElement is CIM_Trace)
                    Target.WriteSymbolWithKeyset("BTN_POKE_15CHAR", LblLocation, "NAV_B2B_" + AssociatedElement.Name.ToUpper());
                else if (SCADA)
                    Target.WriteDataBoundPicture("DEVICE_SUBSTN", LblLocation, "SUBSTN=" + Substation.Name.ToUpper());
                else
                    Target.WriteDataBoundPicture("ANALOG_SUBSTN_NET", LblLocation, "ST=" + Substation.Name.ToUpper());
                
                //Write our text out with a cam
                for (int a=0; a < SubNames.Count; a++)                
                {
                    String SubName = SubNames[a];
                    Size SubSize;
                    using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
                        SubSize = Size.Ceiling(g.MeasureString(SubName, SystemFonts.CaptionFont));
                    Point SubLocation = new Point(Location.X - ((SubSize.Width - 114) / 2), Location.Y - ((SubSize.Height - 18) / 2));
                    //Shift left if we have to
                    SubLocation.X = Math.Max(SubLocation.X, Location.X+3);
                    if (a == 0)
                        Target.WriteTextWithCamAndGab(SubName, "LINELABEL_LONGNAME_NETMOM", "TEXT_FV_CHR_NONENTRY_SIMPLE_ERCOT", SubLocation, false, false);
                    else if (a == 2 || (a == 1 && SubNames.Count == 2))
                        Target.WriteTextWithCamAndGab(SubName, "LINELABEL_LINE_NETMOM", "TEXT_FV_CHR_NONENTRY_SIMPLE_ERCOT", SubLocation, false, false);
                    else
                        Target.WriteTextWithCamAndGab(SubName, "LINELABEL_SUBSTATION_NETMOM", "TEXT_FV_CHR_NONENTRY_SIMPLE_ERCOT", SubLocation, false, false);                                                
                }
            }
            //Added 12/1/11: Add OTS labels for frequency control
            else if (this.ValueType == enumValueType.FrequencyPanel && !SCADA)
                Target.WriteDataBoundPicture("DTS_UN_FRQ_CTRL", Location, "ST=" + Substation.Name.ToUpper(), "UN=" + ElemName);
            else if (this.ValueType == enumValueType.AnalogLevel && !SCADA)
            {                
                if (Orientation == "V" || Orientation == "H")
                    Orientation = this.Orientation.ToString().Substring(0, 1);

                if (AssociatedElement.TypeName == "cim:ACLineSegment")
                {
                    Target.WriteDataBoundPicture("ANALOG_N_" + ElemType + "_" + Orientation, Location, "ST=" + Substation.Name.ToUpper(), "ND=" + ValueSource.Name.ToUpper(), ElemType + "2=" + ElemName);
                }
                //jlh
                else if (AssociatedElement.TypeName == "cim:SeriesCompensator")
                {
                    Target.WriteDataBoundPicture("ANALOG_N_" + ElemType + "_" + (this.Orientation == MM_OneLine_Element.enumOrientations.Up ? "D" : this.Orientation == MM_OneLine_Element.enumOrientations.Down ? "U" : this.Orientation.ToString().Substring(0, 1)), Location, "ST=" + Substation.Name.ToUpper(), "ND=" + ValueSource.Name.ToUpper(), ElemType + "2=" + ElemName);
                }
                else if (AssociatedElement.TypeName == "cim:SynchronousMachine")
                {
                    Orientation = (Orientation == "U" ? "D" : Orientation == "D" ? "U" : Orientation == "L" ? "R" : Orientation == "R" ? "L" : "?");
                    Target.WriteDataBoundPicture("ANALOG_N_UN_" + Orientation, Location, "ST=" + Substation.Name.ToUpper(), "UN=" + ElemName);
                }
                else if (AssociatedElement.TypeName == "cim:ShuntCompensator")
                {
                    Orientation = (Orientation == "U" ? "D" : Orientation == "D" ? "U" : Orientation == "L" ? "R" : Orientation == "R" ? "L" : "?");
                    Target.WriteDataBoundPicture("ANALOG_N_" + ElemType + "_" + Orientation, Location, "ST=" + Substation.Name.ToUpper(), ElemType + "=" + ElemName);
                }
                else if (ElemType == "XF")
                {
                    //Orientation = this.Orientation.ToString().Substring(0, 1);                    
                    Orientation = xElem.Attributes["Orientation"].Value.Substring(0, 1);
                    Orientation = (Orientation == "U" ? "D" : Orientation == "D" ? "U" : Orientation);

                    //Find the primary winding
                    CIM_Element PrimaryWinding = null;
                    foreach (CIM_Element Winding in AssociatedElement.Parse("cim:TransformerWinding", null))
                        if (Winding.TypeName == "cim:TransformerWinding" && Winding.Attributes["cim:TransformerWinding.windingType"].Contains("primary"))
                            PrimaryWinding = Winding;
                    Target.WriteDataBoundPicture("ANALOG_N_" + ElemType + "_" + Orientation, Location, "ST=" + Substation.Name.ToUpper(), "ND=" + ValueSource.ParseSingle("cim:Terminal>cim:ConnectivityNode", null).Name, ElemType + "2=" + PrimaryWinding.Name.ToUpper());
                }
                else
                {
                    Target.WriteDataBoundPicture("ANALOG_N_" + ElemType + "_" + Orientation, Location, "ST=" + Substation.Name.ToUpper(), ElemType + "=" + ElemName);
                }
            }
            else if ((this.ValueType == enumValueType.AnalogLevel || this.ValueType == enumValueType.AVRValue || this.ValueType == enumValueType.PSSValue || this.ValueType == enumValueType.TapValue) && SCADA)
            {
                String AnalogType;

                if (Orientation == "V")
                    Orientation = "D";
                else if (Orientation == "H")
                    Orientation = "R";

                //If we're a unit, flip our orientations
                if (ElemType == "UN" || ElemType == "CP")
                    Orientation = (Orientation == "U" ? "D" : Orientation == "D" ? "U" : Orientation == "L" ? "R" : Orientation == "R" ? "L" : "?");

                //If we're a breaker, perform a hit test to determine whether we need a directional flip.


                //Determine the proper analog type
                //jlh
                if (AssociatedElement.TypeName == "cim:ACLineSegment" || AssociatedElement.TypeName == "cim:SeriesCompensator")
                    AnalogType = "ANALOG_" + Orientation.Substring(0, 1);
                else if (ValueType == enumValueType.AVRValue)
                    AnalogType = "AVR";
                else if (ValueType == enumValueType.PSSValue)
                    AnalogType = "AVR";
                else if (ValueType == enumValueType.TapValue)
                    AnalogType = "ANALOG_10PNT_TAP";
                else if (ElemType == "XF")
                {
                    Orientation = xElem.Attributes["Orientation"].Value.Substring(0, 1);
                    AnalogType = "ANALOG_10PNT_" + (Orientation == "U" ? "D" : Orientation == "D" ? "U" : Orientation);
                }
                else if (AssociatedElement.TypeName == "cim:Disconnector" || AssociatedElement.TypeName == "cim:Breaker")
                    AnalogType = "ANALOG_10PNT_NOSIGN_" + Orientation.Substring(0, 1);
                else
                    AnalogType = "ANALOG_10PNT_" + Orientation.Substring(0, 1);

                //Look for our measurement point
                CIM_Element Meas = ValueSource.ParseSingle("AnalogValue>Calculation", null);
                if (Meas == null)
                    Meas = ValueSource.ParseSingle("AnalogValue>MeasurementGroup", null);
                if (Meas == null)
                    Meas = ValueSource.ParseSingle("DiscreteValue>MeasurementGroup", null);

                String ValueMap = (ValueSource.TypeName == "cim:Discrete" ? "POINT=" + ValueSource.ParseSingle("DiscreteValue>DiscreteName", null).Name : "ANALOG=" + ValueSource.ParseSingle("AnalogValue>AnalogName", null).Name);

              

                //If we're a SCADA transformer winding, handle accordingly
                if (ElemType == "XF")
                {
                    //Find the primary winding
                    CIM_Element PrimaryWinding = null;
                    foreach (CIM_Element Winding in AssociatedElement.Parse("cim:PowerTransformer<cim:TransformerWinding", null))
                        if (Winding.TypeName == "cim:TransformerWinding" && Winding.Attributes["cim:TransformerWinding.windingType"].Contains("primary"))
                            PrimaryWinding = Winding;

                    //Update our device type if needed
                    CIM_Element TypeName = Meas.ParseSingle("MeasurementLocation>DeviceTypeName", null);
                    if (TypeName != null)
                        ElemType = TypeName.Name;

                    //Write out our winding

                    Target.WriteDataBoundPicture(AnalogType, Location, "SUBSTN=" + Substation.Name.ToUpper(), "DEVTYP=" + ElemType, "DEVICE=" + PrimaryWinding.Name.ToUpper(), "MEAS=" + Meas.Name, ValueMap);
                }
                else
                {
                    Target.WriteDataBoundPicture(AnalogType, Location, "SUBSTN=" + Substation.Name.ToUpper(), "DEVTYP=" + ElemType, "DEVICE=" + ElemName, "MEAS=" + Meas.Name, ValueMap);
                    if (BaseElement is CIM_Trace == false)//[ago] CR55198
                        if (ElemType == "LN" && ElemType != "XF" && ValueMap == "ANALOG_MW" && AnalogType != "ANALOG_U")//[ago] CR55198
                            Target.WriteDataBoundPicture("OUTAGE_TYPE", Location, "MASEQP=" + AssociatedElement.TEID); //[ago] CR55198
                }
            }

            else if (this.ValueType == enumValueType.BreakerSwitchLabel)
            {
                if (this.ValueSource == null)
                    Target.WriteTextWithGab(ElemName, "TEXT_FV_CHR_NONENTRY_SIMPLE_ERCOT", Location, false, false);
                else if (SCADA)
                    Target.WriteDataBoundPicture("CB_SW_SCADA_LABEL", Location, "SUBSTN=" + Substation.Name.ToUpper(), "DEVTYP=" + ElemType, "DEVICE=" + ElemName, "MEAS=" + ValueSource.Name, "POINT=" + ValueSource.ParseSingle("DiscreteValue>DiscreteName", null).Name);
                else if (ElemType == "CB")
                {
                    bool HasSynchroscope = Synchroscopes.ContainsKey(Substation.rdfID) || Synchroscopes.ContainsKey(AssociatedElement.rdfID) || Synchroscopes.ContainsKey((AssociatedElement.FindOperator().rdfID));
                    bool HasSynchrocheck = Synchrocheck_Relays.ContainsKey(Substation.rdfID) || Synchrocheck_Relays.ContainsKey(AssociatedElement.rdfID) || Synchrocheck_Relays.ContainsKey((AssociatedElement.FindOperator().rdfID));
                    if (HasSynchrocheck && HasSynchroscope)
                        Target.WriteDataBoundPicture("CB_SW_NET_LABEL_DTS_SYNCHROSCOPE ", Location, "ST=" + Substation.Name.ToUpper(), "CBTYP=" + ElemType, "CB=" + ElemName);
                    else if (HasSynchroscope)
                        Target.WriteDataBoundPicture("CB_SW_NET_LABEL_DTS_SYNC", Location, "ST=" + Substation.Name.ToUpper(), "CBTYP=" + ElemType, "CB=" + ElemName);
                    else if (HasSynchrocheck)
                        Target.WriteDataBoundPicture("CB_SW_NET_LABEL_DTS_SYNCRY", Location, "ST=" + Substation.Name.ToUpper(), "CBTYP=" + ElemType, "CB=" + ElemName);
                    else
                        Target.WriteDataBoundPicture("CB_SW_NET_LABEL", Location, "ST=" + Substation.Name.ToUpper(), "CBTYP=" + ElemType, "CB=" + ElemName);
                }
                else
                    Target.WriteDataBoundPicture("CB_SW_NET_LABEL", Location, "ST=" + Substation.Name.ToUpper(), "CBTYP=" + ElemType, "CB=" + ElemName);

                if (BaseElement is CIM_Trace == false)//[ago] CR55198
                    Target.WriteDataBoundPicture("OUTAGE_TYPE", Location, "MASEQP=" + AssociatedElement.TEID); //[ago] CR55198

            }
            else
            { }
        }
        #endregion
    }
}